package com.company.thread;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.atomic.AtomicStampedReference;

/**
 * @description: CAS的ABA问题产生和解决
 * @author: ruoan
 * @date: 2020/12/8 15:35
 */
@Slf4j
public class CASDemo3 {

    public static void main(String[] args) {



        log.info("----------下面演示ABA问题的产生----------");

        AtomicReference<Integer> atomicReference = new AtomicReference<>(1);

        new Thread(() -> {
            atomicReference.compareAndSet(1, 100);
            atomicReference.compareAndSet(100, 1);

        },"t1").start();


        new Thread(() -> {
            try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); }
            log.info(Thread.currentThread().getName() + ",更新情况：" + atomicReference.compareAndSet(1, 1000));
        },"t2").start();

        //log.info(Thread.currentThread().getName()+": "+atomicReference.get().toString());



        try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); }

        log.info("----------下面演示ABA问题的解决----------");

        AtomicStampedReference<Integer> atomicStampedReference = new AtomicStampedReference<>(1,1);

        new Thread(() -> {
            log.info(Thread.currentThread().getName()+" 当前版本号："+atomicStampedReference.getStamp());
            try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); }
            atomicStampedReference.compareAndSet(1, 100, atomicStampedReference.getStamp(), atomicStampedReference.getStamp() + 1);
            atomicStampedReference.compareAndSet(100, 1, atomicStampedReference.getStamp(), atomicStampedReference.getStamp() + 1);

        },"t3").start();


        new Thread(() -> {
            int stamp = atomicStampedReference.getStamp();
            log.info(Thread.currentThread().getName()+"获取到的版本号为"+stamp);
            try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); }
            log.info(Thread.currentThread().getName() + ":预期结果成功？ " +
                    atomicStampedReference.compareAndSet(1, 1000, stamp, stamp + 1));

            Integer reference = atomicStampedReference.getReference();
            log.info(Thread.currentThread().getName()+"当前原子引用的最终值为："+reference);
        },"t4").start();




    }

}
